/*
 * XPacket.h
 *
 *  Created on: 2009-3-22
 *      Author: gzh
 */

#ifndef XPACKET_H_
#define XPACKET_H_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <stdio.h>
#include <assert.h>
#include <queue>

using namespace std;
/**
 *	WANACC的数据包WANACC的数据包WANACC的数据包
 */
enum XPACKET_TYPE
{
	XPACKET_TYPE_NONE,
	XPACKET_TYPE_OOB,		//OOB包，穿过各层，承载加速栈的非应用数据(通知)
	XPACKET_TYPE_MSG,		//消息包，会被msg_handler直接处理的消息
	XPACKET_TYPE_SSD,		//经过加速的会话数据
	XPACKET_TYPE_BYPASS,	//bypass的会话数据
};

enum ERROR{
	err_noerror,
	err_outmemory
};

#define HTP_SMALL_PK_SIZE 351

class XPacket
{
public:
	XPacket()
		: m_dhandle(0)//m_pSession(0)
		, m_shandle(0)//m_nSsno(0)
		, m_nShead(0)
		, m_pkType(XPACKET_TYPE_NONE)
		, m_pHead(0), m_pTail(0), m_pBuf(0), m_pEnd(0), m_small_flag(0)
	{}
	XPacket(XPACKET_TYPE type, int dhandle,int shandle,/*session* pss, int ssno, */int shead = 0)
		: m_dhandle(0)//m_pSession(pss)
		, m_shandle(0)//m_nSsno(ssno)
		, m_nShead(shead)
		, m_pkType(type)
		, m_pHead(0), m_pTail(0), m_pBuf(0), m_pEnd(0), m_small_flag(0)
	{}
	XPacket(const XPacket& rhs){
		copy_xpacket_param(rhs);
		copy_buf(rhs);
	}
	XPacket& operator=(const XPacket& rhs){
		if (this != &rhs){
			free_buf();
			copy_xpacket_param(rhs);
			copy_buf(rhs);
		}
		return *this;
	}
	~XPacket(){
		free_buf();
	}
public:
	static void deflate_pool();
	static char* alloc_buf(size_t& cnt);
	static void free_buf(char* p, size_t cnt);

	//	分配缓冲区，数据区长度为nData,数据区前方保留nHead字节，后方保留nTail字节
	char* alloc_buf(size_t nData, size_t nHead, size_t nTail);
//	char* alloc_buf(size_t nData, size_t nTail);
	void free_buf();

	//void swap(XPacket& rhs);
	//void swap_data(XPacket& rhs);

	//	清空数据区，但不释放缓存
	void reset(){
		m_pHead = m_pTail = m_pBuf;
	}

	void set_head(char* p){
		assert(p >= m_pBuf && p <= m_pEnd);
		m_pHead = p;
	}
	void set_tail(char* p){
		assert(p >= m_pBuf && p <= m_pEnd);
		m_pTail = p;
	}
	void set_buf(char* pBuf, char* pBufEnd, char* pHead, char* pTail){
		m_pBuf	= pBuf;
		m_pEnd	= pBufEnd;
		m_pHead	= pHead;
		m_pTail	= pTail;
	}
	char* head_move(int offset){
		m_pHead += offset;
		assert(m_pHead >= m_pBuf && m_pHead <= m_pTail);
		return m_pHead;
	}
public:
	char* get_head() const{				//	数据区头部
		return m_pHead;
	}
	char* get_tail() const{				//	数据区尾部
		return m_pTail;
	}
	char* get_end() const{				//	缓冲结束位置
		return m_pEnd;
	}
	char* get_buf() const{				//	缓冲开始位置
		return m_pBuf;
	}
public:
	char* data_begin() const{
		return m_pHead;
	}
	char* buf_begin() const{
		return m_pBuf;
	}
	char* buf_end() const{
		return m_pEnd;
	}
	char* data_end() const{
		return m_pTail;
	}
	size_t data_size() const{
		return m_pTail-m_pHead;
	}
	size_t buf_size() const{
		return m_pEnd-m_pBuf;
	}
	int is_small_pk() const
	{
		return m_small_flag;
	}
	int set_small_pk_flag(int f)
	{
		return (m_small_flag = f);
	}
//private:
	int splice(const XPacket& rhs, size_t nHead, size_t nTail);	//	接合两个数据包，使其成为一个
private:
	struct slab{
		slab();
		~slab();
		char* alloc_buf(/*[in/out]*/size_t* pSize);
		void free_buf(char* pBuf, size_t size);
		void deflate();
	};
private:
	void copy_buf(const XPacket& rhs);
	void copy_xpacket_param(const XPacket& rhs){
		//m_pSession  = rhs.m_pSession;
		//m_nSsno     = rhs.m_nSsno;
		m_dhandle =rhs.m_dhandle;
		m_shandle =rhs.m_shandle;

		m_nShead	= rhs.m_nShead;
		m_pkType	= rhs.m_pkType;
		m_small_flag = rhs.m_small_flag;
	}
public:
	//session* m_pSession;	//	该数据包的拥有者，发出或接收该数据包的会话关联。
	//int		 m_nSsno;		//  会话号
	int m_dhandle;
	int m_shandle;
	int		 m_nShead;		//	会话代理插件添加的包头大小s
	XPACKET_TYPE  m_pkType; //  包的类型，包括三种……
private:
	char*	m_pHead;		//	数据开始
	char*	m_pTail;		//	数据结束
	char*	m_pBuf;			//	缓冲区开端
	char*	m_pEnd;			//	缓冲区末端
	static slab m_slab;		//	固定大小缓冲区分配
	int		m_small_flag;

};

typedef 	queue<XPacket> 	PacketQueue;

#endif /* XPACKET_H_ */
